package com.bibrApp.difu.utils;


import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Protocol {
    /**
     * __MSG_HEAD_STRING__ = "$"
     * __MSG_FLAG_STRING__ = "##"
     * __MSG_BYTE__ = 64
     * __MSG_FLAG_BYTE__ = 2
     * __MSG_TYPE_BYTE__ = 2
     * __MSG_SIZE_BYTE__ = 4
     * __MSG_FLAG_START__ = 1
     * __MSG_TYPE_START__ = 3
     * __MSG_SIZE_START__ = 5
     * __MSG_DATA_START__ = 9
     * __PROTOBUF__: Protobuf
     * __TYPES__: any
     * __OPTIONS__: Options = {
     * enumname: 'Types',
     * headString: '$',
     * flagString: '##'
     */

    private final static String __MSG_HEAD_STRING__ = "?";
    private final static String __MSG_FLAG_STRING__ = "##";
    private final static int __MSG_BYTE__ = 64;
    private final static int __MSG_FLAG_BYTE__ = 2;
    private final static int __MSG_TYPE_BYTE__ = 2;
    private final static int __MSG_SIZE_BYTE__ = 4;
    private final static int __MSG_FLAG_START__ = 1;
    private final static int __MSG_TYPE_START__ = 3;
    private final static int __MSG_SIZE_START__ = 5;
    private final static int __MSG_DATA_START__ = 9;
    private final static int __PROTOBUF__ = 9;


    private final static String HEAD = "?";//每页开头的标记
    private final static String FLAG = "##";//首页的标记
    private final static int PER_BYTE_LENGTH = 64;//每页的字节长度
    private final static int FLAG_LENGTH = 2;//标记所占字节长度 1个字节2位
    private final static int TYPE_LENGTH = 2;//方法所在字节长度
    private final static int SIZE_LENGTH = 4;//传输的数据所占字节长度


    public static boolean hasHead(ByteBuffer byteBuffer) {
        return ClsPublicUtils.hexStringToString(ClsPublicUtils.bytesToHex(byteBuffer.array()).substring(0, 2)).equals(HEAD);
    }

    public static boolean hasHead(byte[] bytes) {
        return ClsPublicUtils.hexStringToString(ClsPublicUtils.bytesToHex(bytes).substring(0, 2)).equals(HEAD);
    }

    public static boolean hasFlag(ByteBuffer byteBuffer) {
        return ClsPublicUtils.hexStringToString(ClsPublicUtils.bytesToHex(byteBuffer.array()).substring(2, 6)).equals(FLAG);
    }

    public static boolean hasFlag(byte[] bytes) {
        return ClsPublicUtils.hexStringToString(ClsPublicUtils.bytesToHex(bytes).substring(2, 6)).equals(FLAG);
    }

    public static int hasPageNum(byte[] bytes) {
        if (hasHead(bytes) && hasFlag(bytes)) {//有头说明是第一条消息
            ByteBuffer sizeBuf = ByteBuffer.allocate(__MSG_SIZE_BYTE__);
            sizeBuf = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes, __MSG_SIZE_START__, __MSG_SIZE_BYTE__));
            int sizeInt = sizeBuf.getInt();
            return (int) Math.ceil(((double) (sizeInt + __MSG_FLAG_BYTE__ + __MSG_TYPE_BYTE__ + __MSG_SIZE_BYTE__)) / (__MSG_BYTE__ - 1));
        }
        return 0;
    }

    public static int getType(List<byte[]> bytes) {
        if (bytes == null || bytes.size() == 0) {
            return 3;
        }
        ByteBuffer typeBuf = ByteBuffer.allocate(__MSG_TYPE_BYTE__);
        if (!hasHead(bytes.get(0))) {
            return 3;
        }
        typeBuf = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes.get(0), __MSG_TYPE_START__, __MSG_TYPE_BYTE__));
        return Integer.parseInt(ClsPublicUtils.bytesToHex(typeBuf.array()), 16);
    }

    /**
     * 解码 相当于去除协议
     *
     * @return
     */
    public static String decode(List<byte[]> bytes) {
        if (bytes == null || bytes.size() == 0) {
            return "";
        }
        ByteBuffer typeBuf = ByteBuffer.allocate(__MSG_TYPE_BYTE__);
        ByteBuffer sizeBuf = ByteBuffer.allocate(__MSG_SIZE_BYTE__);
        ByteBuffer dataBuf = ByteBuffer.allocate(0);
        int typeInt = -1;
        int sizeInt = -1;
        String typeStr;
        for (int i = 0; i < bytes.size(); i++) {
            if (!hasHead(bytes.get(i))) {
                return "";
            }
            ByteBuffer byteBuffer = null;
            if (hasFlag(bytes.get(i))) {
                typeBuf = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes.get(i), __MSG_TYPE_START__, __MSG_TYPE_BYTE__));
                Log.d("dj", "==type==" + ClsPublicUtils.bytesToHex(typeBuf.array()));
                sizeBuf = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes.get(i), __MSG_SIZE_START__, __MSG_SIZE_BYTE__));
                Log.d("dj", "==size==" + ClsPublicUtils.bytesToHex(sizeBuf.array()));
                sizeInt = sizeBuf.getInt();
                Log.d("dj", "==size=to=int==" + sizeInt);
                byteBuffer = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes.get(i), __MSG_DATA_START__, __MSG_BYTE__ - __MSG_DATA_START__));
            } else {
                byteBuffer = ByteBuffer.wrap(ClsPublicUtils.subByte(bytes.get(i), __MSG_FLAG_START__, __MSG_BYTE__ - __MSG_FLAG_START__));
            }

            ByteBuffer newBuffer = ByteBuffer.allocate(dataBuf.array().length + byteBuffer.array().length);
            dataBuf.position(0);
            newBuffer = newBuffer.put(dataBuf);
            newBuffer = newBuffer.put(byteBuffer);
            dataBuf = newBuffer;
            Log.d("dj", "===dataHex222==" + ClsPublicUtils.bytesToHex(dataBuf.array()));
        }
        if (sizeInt == -1) {
            return "";
        }
        if (dataBuf.array().length < sizeInt) {
            return "";
        }
        dataBuf = ByteBuffer.wrap(ClsPublicUtils.subByte(dataBuf.array(), 0, sizeInt));

        return ClsPublicUtils.bytesToHex(dataBuf.array());
    }

    public static String decodeW(List<byte[]> bytes) {
        if (bytes == null || bytes.size() == 0) {
            return "";
        }

        int size = -1;
        String result = "";
        for (int i = 0; i < bytes.size(); i++) {
            String msg = ClsPublicUtils.bytesToHex(bytes.get(i));
            if (!hasHead(bytes.get(i))) {
                return "";
            }
            if (msg.startsWith("3f2323")) {
                ByteBuffer byteBuffer = ByteBuffer.wrap(bytes.get(i));


                byteBuffer.position(__MSG_DATA_START__);
                byte[] data = new byte[__MSG_BYTE__ - __MSG_DATA_START__];
                byteBuffer.get(data);
                result += ClsPublicUtils.bytesToHex(data);
            } else {
                ByteBuffer byteBuffer = ByteBuffer.wrap(bytes.get(i));
                byteBuffer.position(__MSG_FLAG_START__);
                byte[] data = new byte[__MSG_BYTE__ - __MSG_FLAG_START__];
                byteBuffer.get(data);
                result += ClsPublicUtils.bytesToHex(data);
            }
        }
        return result;
    }

    /**
     * 编码  相当于加个自己的协议
     *
     * @typeHexStr type的16进制字符串
     */
    public static List<byte[]> encode(int type, byte[] data) {
        /*if (data == null) {
            data = "";
        }
        Log.i("dj", "---" + data.length());
        byte[] hexToBytes = ClsPublicUtils.hexToBytes(ClsPublicUtils.strTo16(data));*/

        //添加flag 只有第一页有
        ByteBuffer flagBuffer = ByteBuffer.wrap(ClsPublicUtils.hexToBytes(ClsPublicUtils.strTo16(FLAG)));
        ByteBuffer typeBuffer = ByteBuffer.wrap(ClsPublicUtils.hexToBytes(ClsPublicUtils.numToHex16(type)));
        ByteBuffer sizeBuffer = ByteBuffer.allocate(__MSG_SIZE_BYTE__);

        //传输的数据
        ByteBuffer dataBuffer = ByteBuffer.wrap(data);
        //计算type size的值
        Log.d("dj", "====data===length====" + data.length);
        sizeBuffer.putInt(0, data.length);

        int len = flagBuffer.capacity() + typeBuffer.capacity() + sizeBuffer.capacity() + dataBuffer.capacity();
        ByteBuffer bodyBuffer = ByteBuffer.allocate(len);
        bodyBuffer = bodyBuffer.put(flagBuffer);
        bodyBuffer = bodyBuffer.put(typeBuffer);
        bodyBuffer = bodyBuffer.put(sizeBuffer);
        bodyBuffer = bodyBuffer.put(dataBuffer);
        Log.i("dj", "---" + bodyBuffer.capacity());
        Log.i("dj", "---" + ClsPublicUtils.bytesToHex(bodyBuffer.array()));

        int pageNum = (int) Math.ceil(((double) bodyBuffer.capacity()) / (__MSG_BYTE__ - 1));
        Log.i("dj", "---" + pageNum);
        bodyBuffer.position(0);
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < pageNum; i++) {
            byte[] bytes = new byte[__MSG_BYTE__ - 1];
            int offset = i >= pageNum - 1 ? bodyBuffer.capacity() - i * (__MSG_BYTE__ - 1) : __MSG_BYTE__ - 1;
            bodyBuffer.get(bytes, 0, offset);
            ByteBuffer headBuffer = ByteBuffer.allocate(__MSG_BYTE__);
            headBuffer.put(ClsPublicUtils.hexToBytes(ClsPublicUtils.strTo16(HEAD)));
            headBuffer.put(bytes);
            list.add(headBuffer.array());
        }
        return list;
    }


    /**
     * 解码 Unicode \\uXXXX
     *
     * @param str
     * @return
     */
    public static String decodeUnicode(String str) {
        Charset set = Charset.forName("UTF-16");
        Pattern p = Pattern.compile("\\\\u([0-9a-fA-F]{4})");
        Matcher m = p.matcher(str);
        int start = 0;
        int start2 = 0;
        StringBuffer sb = new StringBuffer();
        while (m.find(start)) {
            start2 = m.start();
            if (start2 > start) {
                String seg = str.substring(start, start2);
                sb.append(seg);
            }
            String code = m.group(1);
            int i = Integer.valueOf(code, 16);
            byte[] bb = new byte[4];
            bb[0] = (byte) ((i >> 8) & 0xFF);
            bb[1] = (byte) (i & 0xFF);
            ByteBuffer b = ByteBuffer.wrap(bb);
            sb.append(String.valueOf(set.decode(b)).trim());
            start = m.end();
        }
        start2 = str.length();
        if (start2 > start) {
            String seg = str.substring(start, start2);
            sb.append(seg);
        }
        return sb.toString();
    }
}
